/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package sa4w.sedna;

import com.lowagie.text.Document;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Properties;
import java.util.TreeSet;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import ru.ispras.sedna.driver.DatabaseManager;
import ru.ispras.sedna.driver.DriverException;
import ru.ispras.sedna.driver.SednaConnection;
import ru.ispras.sedna.driver.SednaSerializedResult;
import ru.ispras.sedna.driver.SednaStatement;
import sa4w.config.Configuration;
import sa4w.interfaces.Response;
import sa4w.interfaces.Server;

/**
 *
 * @author Leonardo Oliveira Moreira
 * 
 */
public class ServerSedna implements Server {

    public boolean isServerConnected() {
        boolean reason = false;
        try {
            String command = "";
            Process p = null;
            if (Configuration.getOperationSystem() == Configuration.LINUX) {
                command = "ps aux";
                p = Runtime.getRuntime().exec(command);
            } else {
                String winCmdList[] = {"cmd", "/c", "tasklist"};
                p = Runtime.getRuntime().exec(winCmdList);
            }
            String line;
            BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
            while ((line = input.readLine()) != null) {
                if (line.contains("se_gov")) {
                    reason = true;
                }
            }
            input.close();
            input = new BufferedReader(new InputStreamReader(p.getErrorStream()));
            while ((line = input.readLine()) != null) {
                reason = false;
            }
            input.close();
        } catch (Exception e) {
            reason = false;
        }
        return reason;
    }

    public Response connectServer(String serverPath) {
        Response response = new Response();
        if (isServerConnected()) {
            response.setReason(true);
            response.addErrorMessage("Server is running");
        } else {
            try {
                String command = "";
                if (Configuration.getOperationSystem() == Configuration.LINUX) {
                    command = serverPath + File.separator + "bin" + File.separator + "./se_gov";
                } else {
                    command = serverPath + File.separator + "bin" + File.separator + "se_gov.exe";
                }
                Process p = Runtime.getRuntime().exec(command);
                String line;
                BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
                while ((line = input.readLine()) != null) {
                    response.addMessage(line);
                    response.setReason(true);
                }
                input.close();
                input = new BufferedReader(new InputStreamReader(p.getErrorStream()));
                while ((line = input.readLine()) != null) {
                    response.addErrorMessage(line);
                    response.setReason(false);
                }
                input.close();
            } catch (Exception e) {
                response.addErrorMessage(e.getMessage());
            }
        }
        return response;
    }

    public Response disconnectServer(String serverPath) {
        Response response = new Response();
        if (!isServerConnected()) {
            response.setReason(true);
            response.addErrorMessage("Server is not running");
        } else {
            try {
                String command = "";
                if (Configuration.getOperationSystem() == Configuration.LINUX) {
                    command = serverPath + File.separator + "bin" + File.separator + "./se_stop";
                } else {
                    command = serverPath + File.separator + "bin" + File.separator + "se_stop.exe";
                }
                Process p = Runtime.getRuntime().exec(command);
                String line;
                BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
                while ((line = input.readLine()) != null) {
                    response.addMessage(line);
                    response.setReason(true);
                }
                input.close();
                input = new BufferedReader(new InputStreamReader(p.getErrorStream()));
                while ((line = input.readLine()) != null) {
                    response.addErrorMessage(line);
                    response.setReason(false);
                }
                input.close();
            } catch (Exception e) {
                response.addErrorMessage(e.getMessage());
            }
        }
        return response;
    }

    public Response startDatabase(String serverPath, String databaseName) {
        Response response = new Response();
        if (!isServerConnected()) {
            response.setReason(false);
            response.addErrorMessage("Server is not running");
        } else {
            try {
                String command = "";
                if (Configuration.getOperationSystem() == Configuration.LINUX) {
                    command = serverPath + File.separator + "bin" + File.separator + "./se_sm " + databaseName;
                } else {
                    command = serverPath + File.separator + "bin" + File.separator + "se_sm.exe " + databaseName;
                }
                Process p = Runtime.getRuntime().exec(command);
                String line;
                BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
                while ((line = input.readLine()) != null) {
                    response.addMessage(line);
                    response.setReason(true);
                }
                input.close();
                input = new BufferedReader(new InputStreamReader(p.getErrorStream()));
                while ((line = input.readLine()) != null) {
                    response.addErrorMessage(line);
                    response.setReason(false);
                }
                input.close();
            } catch (Exception e) {
                response.addErrorMessage(e.getMessage());
            }
        }
        return response;
    }

    public Response stopDatabase(String serverPath, String databaseName) {
        Response response = new Response();
        if (!isServerConnected()) {
            response.setReason(false);
            response.addErrorMessage("Server is not running");
        } else {
            try {
                String command = "";
                if (Configuration.getOperationSystem() == Configuration.LINUX) {
                    command = serverPath + File.separator + "bin" + File.separator + "./se_smsd " + databaseName;
                } else {
                    command = serverPath + File.separator + "bin" + File.separator + "se_smsd.exe " + databaseName;
                }
                Process p = Runtime.getRuntime().exec(command);
                String line;
                BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
                while ((line = input.readLine()) != null) {
                    response.addMessage(line);
                    response.setReason(true);
                }
                input.close();
                input = new BufferedReader(new InputStreamReader(p.getErrorStream()));
                while ((line = input.readLine()) != null) {
                    response.addErrorMessage(line);
                    response.setReason(false);
                }
                input.close();
            } catch (Exception e) {
                response.addErrorMessage(e.getMessage());
            }
        }
        return response;
    }

    public Object connectDatabase(String host, String database, String user, String password) {
        if (!isServerConnected() || (host == null || database == null || user == null || password == null)) {
            return null;
        } else {
            try {
                SednaConnection connection = DatabaseManager.getConnection(host, database, user, password);
                if (! connection.isClose())
                    return connection;
            } catch (Exception e) {
                return null;
            }
        }
        return null;
    }

    public Response disconnectDatabase(Object connection) {
        Response response = new Response();
        SednaConnection sednaConnection = (SednaConnection) connection;
        if (sednaConnection != null) {
            try {
                sednaConnection.close();
                response.setReason(true);
                response.addMessage("Connection closed");
            } catch (DriverException ex) {
                response.setReason(false);
                response.addErrorMessage(ex.getMessage());
                sednaConnection = null;
            }
        }
        return response;
    }

    public String[] getDatabases(String serverPath) {
        File dir = new File(serverPath + File.separator + "cfg");
        if (dir.exists()) {
            TreeSet<String> dbs = new TreeSet<String>();
            File[] files = dir.listFiles(new FileFilter() {

                public boolean accept(File file) {
                    if (!file.isFile() || !file.getName().endsWith("_cfg.xml")) {
                        return false;
                    }
                    return true;
                }
            });
            for (File file : files) {
                String name = file.getName();
                name = name.substring(0, name.lastIndexOf("_cfg.xml"));
                dbs.add(new String(name));
            }
            String[] result = new String[dbs.size()];
            int i = 0;
            for (String db : dbs) {
                result[i] = db;
                i++;
            }
            return result;
        } else {
            return null;
        }
    }

    public String executeQuery(Object connection, String query) throws Exception {
        String results = "";
        SednaConnection sednaConnection = (SednaConnection) connection;
        if (sednaConnection == null) {
            throw new Exception("Database is not connected");
        }
        try {
            sednaConnection.begin();
            SednaStatement ss = sednaConnection.createStatement();
            boolean hasResults = ss.execute(query);
            if (hasResults) {
                SednaSerializedResult ssr = ss.getSerializedResult();
                String item = null;
                while ((item = ssr.next()) != null) {
                    item = item.replaceAll("<", "&lt;");
                    item = item.replaceAll(">", "&gt;");
                    item = item.replaceAll(" ", "&nbsp;");
                    item = item.replaceAll("\n", "<br />");
                    results += item;
                }
            }
            sednaConnection.commit();
            return results;
        } catch (Exception e) {
            try {
                if (sednaConnection != null) {
                    sednaConnection.commit();
                }
                throw new Exception(e.getMessage());
            } catch (DriverException ex) {
                throw new Exception(ex.getMessage());
            }
        }
    }

    public Response createDatabase(String serverPath, String databaseName) {
        Response response = new Response();
        if (!isServerConnected()) {
            response.setReason(false);
            response.addErrorMessage("Server is not running");
        } else {
            try {
                String command = "";
                if (Configuration.getOperationSystem() == Configuration.LINUX) {
                    command = serverPath + File.separator + "bin" + File.separator + "./se_cdb " + databaseName;
                } else {
                    command = serverPath + File.separator + "bin" + File.separator + "se_cdb.exe " + databaseName;
                }
                Process p = Runtime.getRuntime().exec(command);
                String line;
                BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
                while ((line = input.readLine()) != null) {
                    response.addMessage(line);
                    response.setReason(true);
                }
                input.close();
                input = new BufferedReader(new InputStreamReader(p.getErrorStream()));
                while ((line = input.readLine()) != null) {
                    response.addErrorMessage(line);
                    response.setReason(false);
                }
                input.close();
            } catch (Exception e) {
                response.addErrorMessage(e.getMessage());
            }
        }
        return response;
    }

    public Response dropDatabase(String serverPath, String databaseName) {
        Response response = new Response();
        if (!isServerConnected()) {
            response.setReason(false);
            response.addErrorMessage("Server is not running");
        } else {
            try {
                String command = "";
                if (Configuration.getOperationSystem() == Configuration.LINUX) {
                    command = serverPath + File.separator + "bin" + File.separator + "./se_ddb " + databaseName;
                } else {
                    command = serverPath + File.separator + "bin" + File.separator + "se_ddb.exe " + databaseName;
                }
                Process p = Runtime.getRuntime().exec(command);
                String line;
                BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
                while ((line = input.readLine()) != null) {
                    response.addMessage(line);
                    response.setReason(true);
                }
                input.close();
                input = new BufferedReader(new InputStreamReader(p.getErrorStream()));
                while ((line = input.readLine()) != null) {
                    response.addErrorMessage(line);
                    response.setReason(false);
                }
                input.close();
            } catch (Exception e) {
                response.addErrorMessage(e.getMessage());
            }
        }
        return response;
    }

    public String[] getDocuments(Object connection, String databaseName) throws Exception {
        SednaConnection sednaConnection = (SednaConnection) connection;
        if (sednaConnection == null) {
            throw new Exception("Database is not connected");
        }
        try {
            String results = "";
            sednaConnection.begin();
            SednaStatement ss = sednaConnection.createStatement();
            boolean hasResults = ss.execute("doc('$documents')");
            if (hasResults) {
                SednaSerializedResult ssr = ss.getSerializedResult();
                String item = null;
                while ((item = ssr.next()) != null) {
                    results += item;
                }
                sednaConnection.commit();
            }
            DocumentBuilder docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
            org.w3c.dom.Document doc = docBuilder.parse(new InputSource(new StringReader(results)));
            doc.getDocumentElement().normalize();
            NodeList nodes = doc.getFirstChild().getChildNodes();
            ArrayList<String> arrayList = new ArrayList<String>();
            System.out.println(nodes.getLength());
            for (int i = 0; nodes != null && i < nodes.getLength(); ++i) {
                Node node = nodes.item(i);
                if (!(node instanceof org.w3c.dom.Element))
                    continue;
                org.w3c.dom.Element element = (org.w3c.dom.Element) node;
                if (element.getTagName().equals("document")) {
                    arrayList.add(element.getAttribute("name"));
                }
            }
            String[] resultArray = new String[arrayList.size()];
            for (int i = 0; i < resultArray.length; i++)
                resultArray[i] = arrayList.get(i);
            return resultArray;
        } catch (Exception e) {
            try {
                if (sednaConnection != null) {
                    sednaConnection.commit();
                }
                throw new Exception(e.getMessage());
            } catch (DriverException ex) {
                throw new Exception(ex.getMessage());
            }
        }

    }

    public String[] getActiveDatabases(String serverPath) {
        if (!isServerConnected()) {
            return null;
        } else {
            try {
                String command = "";
                if (Configuration.getOperationSystem() == Configuration.LINUX) {
                    command = serverPath + File.separator + "bin" + File.separator + "./se_rc -sm-list";
                } else {
                    command = serverPath + File.separator + "bin" + File.separator + "se_rc.exe -sm-list";
                }
                Process p = Runtime.getRuntime().exec(command);
                String line;
                BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
                ArrayList<String> arrayList = new ArrayList<String>();
                while ((line = input.readLine()) != null) {
                    arrayList.add(line);
                }
                input.close();
                input = new BufferedReader(new InputStreamReader(p.getErrorStream()));
                while ((line = input.readLine()) != null) {
                    
                }
                input.close();
                String[] results = new String[arrayList.size()];
                for (int i = 0; i < results.length; i++)
                    results[i] = arrayList.get(i);
                return results;
            } catch (Exception e) {
                return null;
            }
        }
    }
}
